<html>

<head>
  <!-- !!!: Chrome does not need charset, but Safari must need this meta tag, otherwise Chinese characters will be garbled. -->
  <meta charset="UTF-8" />

  <style>
    :root {
      --light-background-color: #f6f6f6;
      --dark-background-color: #303132;

      --light-text-color: #262626;
      --dark-text-color: #e0e0e0;

      --light-border-color: #868686;
      --dark-border-color: #e0e0e0;

      --iframe-border-width: 1px;

      --iframe-top-margin: 6px;
      --iframe-right-margin: 6px;
      --iframe-bottom-margin: 12px;
      --iframe-left-margin: 6px;

      --big-word-title-font-size: 24px;
      --details-summary-font-size: 18px;
    }

    body {
      font-family: 'system-ui';
      margin: 0px;
      color: var(--light-text-color);
      background-color: var(--light-background-color);
    }

    .big-word-title {
      margin: 8px 0px 0px 8px;
      font-weight: 550;
      font-size: var(--big-word-title-font-size);
    }

    .custom-iframe-container {
      border: var(--iframe-border-width) solid var(--light-border-color);
      border-radius: 7px;

      margin-top: var(--iframe-top-margin);
      margin-right: var(--iframe-right-margin);
      margin-bottom: var(--iframe-bottom-margin);
      margin-left: var(--iframe-left-margin);

      width: calc(100% - var(--iframe-left-margin) - var(--iframe-right-margin) - var(--iframe-border-width) * 2);
    }

    @media (prefers-color-scheme: dark) {
      body {
        background-color: var(--dark-background-color);
        color: var(--dark-text-color);
      }
    }
  </style>
  <style>
    details summary {
      font-weight: 400;
      font-size: var(--details-summary-font-size);
      margin: 5px 0;
      text-align: center;
    }

    details summary::-webkit-details-marker {
      width: 10px;
      height: 10px;
    }

    details summary::before,
    details summary::after {
      content: "";
      display: inline-block;
      width: var(--before-after-summary-width, 0px);
      height: 1px;
      background: var(--light-text-color);
      vertical-align: middle;
    }

    details[open] summary::before {
      margin-right: 5px;
    }

    details[open] summary::after {
      margin-left: 5px;
    }

    details:not([open]) summary::before {
      margin-right: 5px;
    }

    details:not([open]) summary::after {
      margin-left: 5px;
    }

    @media (prefers-color-scheme: dark) {

      details summary::before,
      details summary::after {
        background: var(--dark-text-color);
      }
    }
  </style>
  <script>
    function calculateSummaryTextWidth(summary) {
      const range = document.createRange();
      range.selectNodeContents(summary);
      const textWidth = range.getBoundingClientRect().width;
      return textWidth;
    }
    function updateDetailsSummaryLineWidth() {
      const detailsSummaryList = document.querySelectorAll("details summary");
      for (var i = 0; i < detailsSummaryList.length; i++) {
        const summary = detailsSummaryList[i];
        const summaryText = summary.innerText;
        const computedStyle = getComputedStyle(summary);
        const font = {
          fontSize: computedStyle.fontSize,
          fontWeight: computedStyle.fontWeight,
          fontFamily: computedStyle.fontFamily,
        };
        const summaryTextWidth = calculateSummaryTextWidth(summary);
        const detailsMargin = 10;
        const detailsSummaryTriangleWidth = 20;
        const detailsPadding = 10;
        let summaryLineWidth =
          (document.documentElement.clientWidth -
            detailsMargin -
            summaryTextWidth -
            detailsSummaryTriangleWidth -
            detailsPadding) /
          2;
        summary.style.setProperty(
          "--before-after-summary-width",
          `${summaryLineWidth}px`
        );
      }
    }
    function convertColorsInIframe(iframe, isDarkMode) {
      var iframeDocument = iframe.contentWindow.document;
      var elements = iframeDocument.querySelectorAll("*");
      elements.forEach(function (tag) {
        convertElementColor(tag);
      });

      function convertElementColor(element) {
        var computedStyle = getComputedStyle(element);
        var originalColor = computedStyle.color;
        var newColor = convertColorValue(originalColor, isDarkMode);
        element.style.color = newColor;

        // convert background color if has
        var originalBackgroundColor = computedStyle.backgroundColor;
        if (
          originalBackgroundColor &&
          originalBackgroundColor !== "rgba(0, 0, 0, 0)"
        ) {
          var newBackgroundColor = convertColorValue(
            originalBackgroundColor,
            !isDarkMode
          );
          // newBackgroundColor = revertColorValue(originalBackgroundColor);
          element.style.backgroundColor = newBackgroundColor;

          // console.log(`originalBackgroundColor: ${originalBackgroundColor}`);
          // console.log(`newBackgroundColor: ${newBackgroundColor}`);
        }

        // convert border color if has
        var originalBorderColor = computedStyle.borderColor;
        if (originalBorderColor) {
          var newBorderColor = convertColorValue(
            originalBorderColor,
            isDarkMode
          );
          element.style.borderColor = newBorderColor;

          // console.log(`originalBorderColor: ${originalBorderColor}`);
          // console.log(`newBorderColor: ${newBorderColor}`);
        }
      }

      function isNotCustomBackgroundColor(color) {
        var rootStyles = getComputedStyle(document.documentElement);
        var lightBackgroundColor = rootStyles.getPropertyValue(
          "--light-background-color"
        );
        var darkBackgroundColor = rootStyles.getPropertyValue(
          "--dark-background-color"
        );

        // console.log(`color: ${color}`);
        // console.log(`lightBackgroundColor: ${lightBackgroundColor}`);
        // console.log(`darkBackgroundColor: ${darkBackgroundColor}`);

        return (
          color !== lightBackgroundColor && color !== darkBackgroundColor
        );
      }

      function convertColorValue(color, isDarkMode) {
        const rgbValues = color.match(/\d+/g);
        const r = parseInt(rgbValues[0], 10);
        const g = parseInt(rgbValues[1], 10);
        const b = parseInt(rgbValues[2], 10);
        const brightness = (r + g + b) / 3;
        let brightenAmount = 0;
        const lowBrightnessThreshold = 15;
        const lightLowBrightnessAmount = 255 - lowBrightnessThreshold;
        const ratio = 0.5;
        if (isDarkMode) {
          if (brightness < lowBrightnessThreshold) {
            brightenAmount = lightLowBrightnessAmount;
          } else {
            brightenAmount = lightLowBrightnessAmount * ratio;
          }
        } else {
          if (brightness > lightLowBrightnessAmount) {
            brightenAmount = -lightLowBrightnessAmount;
          } else {
            brightenAmount = -lightLowBrightnessAmount * ratio;
          }
        }
        const adjustedR = Math.min(Math.max(r + brightenAmount, 0), 255);
        const adjustedG = Math.min(Math.max(g + brightenAmount, 0), 255);
        const adjustedB = Math.min(Math.max(b + brightenAmount, 0), 255);
        return `rgb(${adjustedR}, ${adjustedG}, ${adjustedB})`;
      }

      // revert color
      function revertColorValue(color) {
        var colorNumbers = color.match(/\d+/g);
        // console.log(`colorNumbers: ${colorNumbers}`);

        colorNumbers = colorNumbers.map(function (value) {
          var intValue = parseInt(value, 10);
          return 255 - intValue; // 反转颜色值
        });

        return "rgb(" + colorNumbers.join(", ") + ")";
      }
    }

    function isDarkMode() {
      return (
        window.matchMedia &&
        window.matchMedia(`(prefers-color-scheme: dark)`).matches
      );
    }

    function updateAllIframeAppleSystemLabelBorderBottomColor(isDark) {
      var iframes = document.querySelectorAll(`iframe`);
      var newColor = isDark ? "#E0E0E0" : "#262626";
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var iframeDocument = iframe.contentWindow.document;
        var elements = iframeDocument.querySelectorAll(`.x_xoLblBlk`);
        for (var j = 0; j < elements.length; j++) {
          var element = elements[j];
          element.style.borderBottomColor = newColor;
        }
      }
    }

    function updateAllIframeStyle() {
      var iframes = document.querySelectorAll("iframe");
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var iframeDocument = iframe.contentWindow.document;

        // modify iframe body margin
        var body = iframeDocument.querySelector("body");
        body.style.margin = "8px 8px";
        body.style.padding = "0px";

        // 获取body元素的样式
        var bodyStyle = getComputedStyle(iframeDocument.body);

        // 获取iframe元素的计算样式
        var iframeStyle = window.getComputedStyle(iframes[i]);

        // documentElementScrollHeight will >= 150 if we don't set iframe height to 0px
        iframe.style.height = "0px";

        // Ref: https://gist.github.com/ifightcrime/1712614
        var documentElementScrollHeight =
          iframeDocument.documentElement.scrollHeight;
        // console.log(
        //   "documentElementScrollHeight: " + documentElementScrollHeight
        // );

        // var bodyHeight = iframeDocument.body.getBoundingClientRect().height;
        // console.log("bodyHeight: " + bodyHeight);

        // 获取 body 元素的外边距
        var marginTop = parseInt(bodyStyle.getPropertyValue("margin-top"));
        var marginBottom = parseInt(
          bodyStyle.getPropertyValue("margin-bottom")
        );

        var marginHeight = marginTop + marginBottom;
        // console.log("marginHeight: " + marginHeight); // 16

        // 获取 iframe 元素的边框
        var borderTop = parseInt(
          iframeStyle.getPropertyValue("border-top-width")
        );
        var borderBottom = parseInt(
          iframeStyle.getPropertyValue("border-bottom-width")
        );

        var borderHeight = borderTop + borderBottom;
        // console.log("borderHeight: " + borderHeight); // 2

        var scrollHeight = iframeDocument.body.scrollHeight;
        // console.log("scrollHeight: " + scrollHeight);

        // 计算总高度
        var totalHeight = scrollHeight + marginHeight + borderHeight;

        // 我也不知道为什么要加这个判断，但是不加的话，有些页面会出现滚动条 😢
        // 但 documentScollHeight 最小值是 150，所以这里判断一下。hackathon
        // if (totalHeight <= documentScollHeight && documentScollHeight > 150) {
        //   totalHeight = documentScollHeight + borderHeight;
        // }

        totalHeight = documentElementScrollHeight;

        // 设置 iframe 的高度
        iframe.style.height = totalHeight + "px";

        // console.log(`${i}: frame totalHeight: ${totalHeight}`);


        var scrollHeight = getScrollHeight();

        if (window.webkit && window.webkit.messageHandlers) {
          // 调用 objc 方法
          window.webkit.messageHandlers.objcHandler.postMessage({
            method: "noteToUpdateScrollHeight",
            scrollHeight: scrollHeight,
          });
        }
      }
    }

    // get all iframe height, return height array
    function getIframeHeights() {
      var heights = [];
      var iframes = document.querySelectorAll("iframe");
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var iframeDocument = iframe.contentWindow.document;
        var documentElementScrollHeight =
          iframeDocument.documentElement.scrollHeight;
        heights.push(documentElementScrollHeight);
      }
      return heights;
    }

    // get total scroll height
    function getScrollHeight() {
      /**
       * one iframe, iframesHeight: 99, scrollHeight: 184
       * two iframe, iframesHeight: 443, scrollHeight: 572
       *
       * 184-99 = 85
       * 572-443 = 129
       * 85*2 = 170
       * 170-129 = 41
       * bigWordTitleHeight = 41
       * dictionaryTitleHeight = 85-41 = 44
       */

      var bigWordTitleHeight = 41;
      var dictionaryTitleHeight = 44;
      var iframesHeight = getIframeHeights();
      var allIframesHeight = iframesHeight.reduce(function (a, b) {
        return a + b;
      }, 0);
      var scrollHeight =
        bigWordTitleHeight +
        allIframesHeight +
        dictionaryTitleHeight * iframesHeight.length;

      // console.log(`iframesHeight: [${iframesHeight}]`);
      // console.log(`scrollHeight: ${scrollHeight}`);

      return scrollHeight;
    }

    // update all iframe color
    function updateAllIframeColor(isDarkMode) {
      var iframes = document.querySelectorAll("iframe");
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        convertColorsInIframe(iframe, isDarkMode);
      }
    }

    // update body background color and all iframe background color
    function updateBackgroundColor(isDarkMode) {
      var rootStyles = getComputedStyle(document.documentElement);
      var lightBackgroundColor = rootStyles.getPropertyValue(
        "--light-background-color"
      );
      var darkBackgroundColor = rootStyles.getPropertyValue(
        "--dark-background-color"
      );

      // update body background color
      var newBackgroundColor = isDarkMode
        ? darkBackgroundColor
        : lightBackgroundColor;
      document.body.style.backgroundColor = newBackgroundColor;

      // update all iframe background color
      var iframes = document.querySelectorAll("iframe");
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var iframeDocument = iframe.contentWindow.document;
        var newBackgroundColor = isDarkMode
          ? darkBackgroundColor
          : lightBackgroundColor;
        iframeDocument.body.style.backgroundColor = newBackgroundColor;

        // update iframe border color
        var lightBorderColor = rootStyles.getPropertyValue(
          "--light-border-color"
        );
        var darkBorderColor = rootStyles.getPropertyValue(
          "--dark-border-color"
        );

        var newBorderColor = isDarkMode ? darkBorderColor : lightBorderColor;
        iframe.style.borderColor = newBorderColor;
      }
    }

    // Change font size
    function changeIframeBodyFontSize(fontSizeRatio) {
      var percentFontSize = fontSizeRatio * 100 + "%";
      // console.log("fontSize: " + fontSizeRatio);

      // change body font size
      document.body.style.fontSize = percentFontSize;

      // change .big-word-title font size
      var rootStyles = getComputedStyle(document.documentElement);
      var originalBigWordTitleFontSize = rootStyles.getPropertyValue(
        "--big-word-title-font-size"
      );
      var bigWordTitle = document.querySelector(".big-word-title");
      changeElementFontSize(bigWordTitle, originalBigWordTitleFontSize, fontSizeRatio);

      // change details summary font size
      var detailsSummaryList = document.querySelectorAll("details summary");
      for (var i = 0; i < detailsSummaryList.length; i++) {
        var summary = detailsSummaryList[i];
        var originalDetailsSummaryFontSize = rootStyles.getPropertyValue(
          "--details-summary-font-size"
        );
        changeElementFontSize(summary, originalDetailsSummaryFontSize, fontSizeRatio);
      }

      // change all iframe body font size
      var iframes = document.getElementsByTagName('iframe');
      for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var frameDoc = iframe.contentDocument || iframe.contentWindow.document;

        // 修改 iframe 中 body 的字体大小
        frameDoc.body.style.fontSize = percentFontSize;
      }
    }

    function changeElementFontSize(element, originalFontSize, fontSizeRatio) {
      // console.log(`originalFontSize: ${originalFontSize}`);
      var newFontSize = parseFloat(originalFontSize) * fontSizeRatio;
      // console.log(`newFontSize: ${newFontSize}`);
      element.style.fontSize = newFontSize + 'px';
    }

    window.onload = function () {
      // 重写 console.log，以便在 Xcode 中输出日志
      if (
        !window.consoleLogRedefined &&
        window.webkit &&
        window.webkit.messageHandlers
      ) {
        window.consoleLogRedefined = true;
        var originalConsoleLog = console.log;
        console.log = function (message) {
          window.webkit.messageHandlers.objcHandler.postMessage({
            method: "consoleLog",
            message: message,
          });
        };
      }

      var colorSchemeListener = window.matchMedia(
        `(prefers-color-scheme: dark)`
      );
      colorSchemeListener.addEventListener(`change`, function (event) {
        var isDarkMode = event.matches;
      });
    };
  </script>
</head>

<body></body>

</html>
